iT邦幫忙

2026 iThome 鐵人賽

DAY 22
0
Vibe Coding

從課堂半成品到完整發布:獨立遊戲的30天重生記系列 第 22 篇

【DAY22】Unity 2D 敘事遊戲開發:Bad End 條件判定與決策流攔截機制(GameConditionManager )

  • 分享至 

  • xImage
  •  

一、 前言
在敘事與經營類遊戲中,如果讓玩家在前期不小心選錯一個選項就瞬間強制 Game Over,往往會大打折扣,甚至讓玩家感到挫折而棄坑。所以今天我們就要專注實作 DAY22 的核心規則:建立獨立的 Bad End 結局場景,並在選項管理器中加入 「決策攔截機制」,當關鍵數值低於門檻時,才正式進入壞結局!

二、 Bad End 需求與防呆挑戰
實作 Bad End 轉換與數值判定時,程式必須依序克服以下幾個痛點:

  • **時間軸開場重設(Time.timeScale = 1f):**在切換到結局場景的第一行強制將時間軸恢復正常,避免因先前觸發某些特效或暫停導致結局畫面卡死。
  • 清除全域暫停旗標(IsGamePaused = false): 重設全域狀態條件,確保進入 Bad End 畫面後,系統不會誤以為遊戲還在暫停狀態中而無法操作。
  • 場景安全載入(SceneManager.LoadScene): 順利將畫面切換到我們精心設計的 BadEnd_Choices 像素美術結局場景。
  • 決策流攔截(Gatekeeper Pattern): 不能在扣點數的瞬間直接斷頭,而是要在 PaperManager 進行決策結算時,安插一層防線去檢查數值,若低於門檻則強制覆蓋原本要去的通關場景。

三、 核心程式實作:PaperManager 與 GameConditionManager 結合
我們將判定邏輯拆分為獨立的 GameConditionManager 來管理結局場景設定與防呆跳轉,並在 PaperManager 的決策執行函式中加入攔截機制。

  1. 首先是負責獨立場景與防呆跳轉的 GameConditionManager.cs:
using UnityEngine;
using UnityEngine.SceneManagement;

public class GameConditionManager : MonoBehaviour {
    [Header("結局場景設定")]
    public string badEndSceneName = "BadEnd_Choices"; // 對應你的 Bad End 獨立場景名稱

    // 檢查遊戲勝負條件
    public void CheckGameOverCondition(int currentStat)  {
        if (currentStat < 5) {
            TriggerBadEnd();
        }
    }
    private void TriggerBadEnd() {
        // 1. 【防呆】切換場景前務必恢復時間軸
        Time.timeScale = 1f;

        // 2. 清除全域暫停狀態旗標
        PauseMenuController.IsGamePaused = false;

        // 3. 載入 Bad End 獨立場景
        SceneManager.LoadScene(badEndSceneName);
        
        Debug.Log("觸發 Bad End,正在前往結局場景...");
    }
}
  1. 接著是修改 PaperManager.cs 中的 ProcessDecision 函式,在數值變動後、場景跳轉前加入攔截邏輯:
private void ProcessDecision(int moneyChange, int reputationChange, string targetScene, string debugTag) {
        if (statsManagerCache == null) FindStatsManager();
        if (statsManagerCache != null) {
            // 1. 執行數值變動
            statsManagerCache.HandleDecision(moneyChange, reputationChange);
            Debug.Log($"{debugTag} 決策執行:金錢 {moneyChange}, 聲譽 {reputationChange}");

            // 2. 關閉 UI
            HideDocumentDecision();

            // 3. 【關鍵攔截】檢查更新後的數值是否觸發 Bad End
            GameConditionManager conditionManager = GetComponent<GameConditionManager>();
            if (conditionManager != null) {
                // 以聲譽或關鍵數值作為判定依據
                int currentReputation = PlayerStatsManager.Instance.reputation;
                if (currentReputation < 5) {
                    Debug.Log("數值低於 5,強制導向 Bad End!");
                    SceneManager.LoadScene(conditionManager.badEndSceneName);
                    return; // 終止後續,直接返回
                }
            }

            // 4. 原本根據選項跳轉不同場景
            if (!string.IsNullOrEmpty(targetScene)) {
                SceneManager.LoadScene(targetScene);
            }
            else {
                Debug.LogWarning($"{debugTag} 選項未設定目標場景名稱!");
            }
        }
        else {
            Debug.LogError("無法處理決策,因為找不到 StatsManager。");
        }
    }

四、 Unity Inspector 設定與實測驗收(只需掛載在最後一幕)

  1. 腳本掛載: 將 GameConditionManager 與 PaperManager 同時掛載在場景中的 GameManager 物件上。
  2. 參數指定:
  • 在 GameConditionManager 的 Inspector 中,確認 Bad End Scene Name 欄位正確填入 BadEnd_Choices。
  • 在 PaperManager 中確認各項決策的數值增減與目標場景(如 SuccessScene)已正確對應。
  1. 實測驗收: 進入遊戲並故意做出會大量扣除聲譽或數值的選擇,當數值低於 5 時,系統成功攔截原本要前往的普通場景,順利切換至 BadEnd_Choices 結局畫面。
    https://ithelp.ithome.com.tw/upload/images/20260929/20184073uGaa3VzPYk.png
    圖一、腳本掛載示意圖

https://ithelp.ithome.com.tw/upload/images/20260929/20184073UL0AtwWxWi.png
圖二、BadEnd_Choices Scene

五、 開發實戰經驗:踩坑與架構反思

  • 避免直接跳轉漏掉判定: 一開始測試時直接呼叫SceneManager.LoadScene(targetScene) 導致數值小於 5 時依然被帶去好結局。透過在 PaperManager 的 ProcessDecision 內安插「閘道器」進行前置檢查,才能完美掌控分歧點。
  • 新舊 API 升級警示: 在撰寫尋找管理器或物件時,留意 Unity 6 已逐漸將舊版的 FindObjectOfType 標記為過時,建議可改用效能與語意更明確的 FindFirstObjectByType,保持程式碼的整潔與現代化。

六、 今日成果與小結

  • Bad End 獨立場景串接: 成功建立具備氛圍感的結局場景,並透過防呆機制確保時間軸與暫停狀態不留殘渣。
  • 決策流攔截完成: 完美結合 PaperManager 與數值判定,讓劇情遊戲的勝負判定更具深度與邏輯性。

範例影片:Yes

今天的內容屬於遊戲的核心遊戲迴圈(Gameplay Loop)與遊戲狀態/結局判定系統,所以會建立一個專屬的新分支--feature/game-condition來管理!

1.檢查目前修改狀態
git status

2.建立並切換至新的獨立分支:
git checkout -b feature/game-condition

3.將今天的程式碼與修改加入暫存區並提交 Commit:
git add .
git commit -m "feat: 實作 GameConditionManager 與 PaperManager 決策攔截機制,完成 Bad End 獨立場景跳轉與數值勝負判定"

4.將新分支推送到遠端倉庫:
git push origin feature/game-condition


上一篇
【DAY21】Unity 2D 敘事遊戲開發:主選單返回機制與時間軸防呆重設(GoToMainMenu)
下一篇
【DAY23】Unity 2D 敘事遊戲開發:成就系統核心架構與資料模型(Achievement System Part 1 - Data & ScriptableObject)
系列文
從課堂半成品到完整發布:獨立遊戲的30天重生記 共 24 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言